package util;

import java.math.BigInteger;

public class UInt64 extends Number implements Comparable<UInt64> {

    private static final long serialVersionUID = 8663821253565166565L;
    
    private BigInteger value;
    
    public static BigInteger MAX_VALUE = new BigInteger("18446744073709551615");
    public static BigInteger MIN_VALUE = new BigInteger("0");
    
    public UInt64(BigInteger value) throws NumberFormatException {
            this.value = value;
            if(value.compareTo(MAX_VALUE) > 0 || value.compareTo(MIN_VALUE) < 0)
                    throw new NumberFormatException("The number must be from " + MIN_VALUE + " - " + MAX_VALUE + "!");
    }
    
    public UInt64(String s) throws NumberFormatException {
            value = new BigInteger(s);
            if(value.compareTo(MAX_VALUE) > 0 || value.compareTo(MIN_VALUE) < 0)
                    throw new NumberFormatException("The number must be from " + MIN_VALUE + " - " + MAX_VALUE + "!");
    }
    
    public UInt64(byte[] key) {
    	byte tmp[] = new byte[key.length+1];
    	tmp[0]=0;
    	for(int i=0;i<key.length;i++){
    		tmp[i+1]=key[i];
    	}
		this.value= new BigInteger(tmp);
		if(value.compareTo(MAX_VALUE) > 0 || value.compareTo(MIN_VALUE) < 0)
            throw new NumberFormatException("The number must be from " + MIN_VALUE + " - " + MAX_VALUE + "!");
	}

    
    
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((value == null) ? 0 : value.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		UInt64 other = (UInt64) obj;
		if (value == null) {
			if (other.value != null)
				return false;
		} else if (!value.equals(other.value))
			return false;
		return true;
	}

	public UInt64 xor(UInt64 val){    	
    	return new UInt64(this.value.xor(val.value)); 
    }
    
    @Override
    public double doubleValue() {
            return value.doubleValue();
    }

    @Override
    public float floatValue() {
            return value.floatValue();
    }

    @Override
    public int intValue() {
            return value.intValue();
    }

    @Override
    public long longValue() {
            return value.longValue();
    }

    @Override
    public int compareTo(UInt64 anotherUInt64) {
            return value.compareTo(anotherUInt64.value);
    }
    
    public String toString(){
    	return value.toString(16);
    }
}
